#include "Precomp.h"
#include "ltMapFactory.h"
#include "ltMapState.h"
#include "mapformat.pb.h"
#include <fstream>
#include "ltGraphicManager.h"
#include "OgreODE/OgreODE_Core.h"

using namespace std;
using namespace Ogre;

namespace Lotus
{
	LT_IMPLEMENT_SINGLETON(MapFactoryBase);

	MapFactoryBase::MapFactoryBase()
	{
		sceneManagerDictionary.insert(std::make_pair(Ogre::String("GENERIC"),ST_GENERIC));
		sceneManagerDictionary.insert(std::make_pair(Ogre::String("EXTERIOR_CLOSE"),ST_EXTERIOR_CLOSE));
		sceneManagerDictionary.insert(std::make_pair(Ogre::String("EXTERIOR_FAR"),ST_EXTERIOR_FAR));
		sceneManagerDictionary.insert(std::make_pair(Ogre::String("EXTERIOR_REAL_FAR"),ST_EXTERIOR_REAL_FAR));
		sceneManagerDictionary.insert(std::make_pair(Ogre::String("INTERIOR"),ST_INTERIOR));
	}


	MapFactoryBase::~MapFactoryBase()
	{
	}

	MapState* MapFactoryBase::createMapFromFile(const char* file)
	{
		mapformat::Map mapdata;
		fstream in(file,ios_base::in|ios_base::binary);
		mapdata.ParseFromIstream(&in);
		in.close();

		MapState* map=createBlankMap(mapdata.scenetype().c_str());
		foreach(mapformat::MapObject& objectData,*(mapdata.mutable_objects()))
		{
			map->loadObject(&objectData,NULL);
		}
		return map;
	}

	void MapFactoryBase::saveMapToFile(MapState* map,const char* file)
	{
		mapformat::Map mapdata;
		mapdata.set_scenetype(map->sceneManager->getTypeName().c_str());
		foreach(MapObject* object,map->objects)
		{
			mapformat::MapObject* objectData=mapdata.add_objects();
			map->saveObject(object,objectData);
		}
		fstream out(file,ios_base::out|ios_base::binary);
		mapdata.SerializeToOstream(&out);
	}

	MapState* MapFactoryBase::createBlankMap(const char* sceneType)
	{
		MapState* map=newMap();
		std::map<String,SceneType>::iterator i=sceneManagerDictionary.find(sceneType);
		if(i!=sceneManagerDictionary.end())//known type
			map->sceneManager=GraphicManager::getInstance().getOgreRoot()->createSceneManager(i->second);
		else//unknown, this can be a plugin
			map->sceneManager=GraphicManager::getInstance().getOgreRoot()->createSceneManager(sceneType);
		map->physicWorld=new OgreOde::World(map->sceneManager);
		map->mStepper=new OgreOde::StepHandler(map->physicWorld);
		map->physicWorld->setCollisionListener(map);
		return map;
	}
}